package com.sap.health.tracker.threads;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.androidplot.xy.BoundaryMode;
import com.androidplot.xy.LineAndPointFormatter;
import com.androidplot.xy.LineAndPointRenderer;
import com.androidplot.xy.XYPlot;
import com.sap.health.tracker.R;
import com.sap.health.tracker.graph.GraphHolder;
import com.sap.health.tracker.json.JSONFunctions;
import com.sap.health.tracker.library.StoreData;


import android.os.Bundle;
import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PointF;
import android.util.FloatMath;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class LogThread extends Activity implements OnTouchListener {

	// JSON Response node names	
	private static String KEY_SUCCESS = "success";
    private static String KEY_UID = "uid";
    private static String KEY_SESSION = "session";
    private static final String STATE_SELECTED_NAVIGATION_ITEM = "selected_navigation_item";
	private String mUserID;
	private String mSessionToken;	
	private String mSeverityStr = "0";
    private ProgressDialog mLoadingDialog;
	private Context mCtx;
    private TextView mGetLogErrorMsg;	
	private int mSpinnerSelected = 0;	
	private int mRulerColour = 0xFFDEDEDE;
	private int mCurrentTab = 0;	
	private JSONArray mJsonLogs;
	private JSONArray mJsonTypes;	
	private ArrayList<String> mLogTypeStringArray = new ArrayList<String>();
	private ArrayList<String> mLogTypeIdArray = new ArrayList<String>();
	private ArrayList<String> mSeverityStringArray = new ArrayList<String>();
	private ArrayAdapter<String>  mLogAdapter;
	private Spinner mLogTypeSpin;
	private Spinner mSeveritySpin;
	private Button mAdd;	
	private EditText mValueText;
	private EditText mNotesText; 
	private EditText mSymptomsText;
	private EditText mFoodText;
	private EditText mCaloriesText; 
	private TableLayout mValueTable;
	private TableLayout mComparisonTable;
	private TableLayout mDateTable;
	private TableLayout mAllTable;
	private TableLayout mLogTable;		 
	private boolean mHistory = false;
	private boolean mTypesBool = false;
	private boolean mCompare = false;
	private boolean mHuman = false;
	private boolean mDialogBool = false;	 	 
	// Global variabels for the graph
	private GraphHolder mySeries;
	private PointF minXY;
	private PointF maxXY;		
	private Vector<Double> vector = new Vector<Double>();    
	private XYPlot graphLayout;
	private Spinner graphLogTypeSpiner = null;
	// Definition of the touch states
	static final int NONE = 0;
	static final int ONE_FINGER_DRAG = 1;
	static final int TWO_FINGERS_DRAG = 2;
	private int mMode = NONE;	
	private PointF mFirstFinger;
	private float mLastScrolling;
	private float mDistBetweenFingers;
	private float mLastZooming;
	/**
	 * Main constructor 
	 * @param ctx
	 * @param userId
	 * @param sessionToken
	 * @param refresh
	 */
	public LogThread(Context ctx, 
			 	String userId, 
			 	String sessionToken,
	    		final ImageView refresh){
		this.mCtx = ctx; 
		this.mUserID = userId;
		this.mSessionToken = sessionToken;		
		refresh.setOnClickListener(new OnClickListener() {
		 	public void onClick(View v) {
		 		refresh();
		 	}
		 });	               
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);             
        // needed but not used.
    }  
    
    @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
        if (savedInstanceState.containsKey(STATE_SELECTED_NAVIGATION_ITEM)) {
            getActionBar().setSelectedNavigationItem(
                    savedInstanceState.getInt(STATE_SELECTED_NAVIGATION_ITEM));
        }
    }
    
    @Override
    public void onSaveInstanceState(Bundle outState) {
        outState.putInt(STATE_SELECTED_NAVIGATION_ITEM,
                getActionBar().getSelectedNavigationIndex());
    }
    /**
     * Log Graph Setup
     * @param graphLayoutID
     * @param graphLogTypeSpin
     */
    public void logGraphSetup(final XYPlot graphLayoutID, final Spinner graphLogTypeSpin){
    	
    	this.graphLayout = graphLayoutID;
    	this.graphLogTypeSpiner = graphLogTypeSpin;    	
    	graphLogTypeSpiner.setVisibility(View.VISIBLE);           	
    	graphLayout.setTitle("");				    		        	    		
    	graphLayout.setOnTouchListener(this);   	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    	    	// let user know it's busy.
    			createProgressDialog();		          	          	          	
            	// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);
            	// connect to server and get logs.
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.getLogs(mUserID, mSessionToken);                            
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {              		
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// check if logs is null
                			if(!json.isNull("dataTypeList")){
		            			mJsonTypes = json.getJSONArray("dataTypeList");
		            			//make sure these are empty - avoids dublicate values.
		            			mLogTypeStringArray.clear();
		            			mLogTypeIdArray.clear();
		            			// add the type names to a string array.
		            			for(int n = 0; n < mJsonTypes.length(); n++){
		            				String name = mJsonTypes.getJSONObject(n).getString("datalog_type_name");
		            				//convert the first character to uppercase.
		            				name = name.substring(0, 1).toUpperCase() + name.substring(1);                				
		            				mLogTypeStringArray.add(name);
		            				// get the id numbers in the same order as the names ->used for adding log.
		            				mLogTypeIdArray.add(mJsonTypes.getJSONObject(n).getString("datalog_type_id"));
		            			}
		            			runOnUiThread(new Runnable() {
		        		            public void run() {
		        		            	graphLogTypeSpiner.setOnItemSelectedListener(new OnItemSelectedListener() {
				    		        	    @Override
				    		        	    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
				    		        	    	mSpinnerSelected = position;			    		        	    					    		        	    						    		        	    		
				    		        	    	//Plot layout configurations
				    		        	    	graphLayout.getGraphWidget().setTicksPerRangeLabel(1);
				    		        	    	graphLayout.getGraphWidget().setTicksPerDomainLabel(1);
				    		        	    	graphLayout.getGraphWidget().setRangeValueFormat(
				    		        	    				new DecimalFormat("#####.##"));
				    		        	    	graphLayout.getGraphWidget().setDomainValueFormat(
				    		        	    				new DecimalFormat("#####.##"));
				    		        	    	graphLayout.getGraphWidget().setRangeLabelWidth(25);
				    		        	    	graphLayout.setRangeLabel("Value");
				    		        	    	graphLayout.setDomainLabel("Per Day");
				    		        	    	graphLayout.disableAllMarkup();				    		        	    		
				    		        	    	// used for refreshing.
				    		        	        mCurrentTab = 1;		
				    		        	    	// get graph data from the server.
				    		        	    	getGraphData(graphLogTypeSpiner.getSelectedItem().toString());				    		        	    					    		        	    	
				    		        	    }
				    		        	    @Override
				    		        	    public void onNothingSelected(AdapterView<?> parentView) {
				    		        	        // do nothing.
				    		        	    }                   		        
										});		        		        
										// Create an ArrayAdapter using the string array and a default spinner layout	    		        						
		        		            	ArrayAdapter<String> logAdapter = new ArrayAdapter<String>(mCtx,
		                        	    		android.R.layout.simple_spinner_item, mLogTypeStringArray);  	    
		                        	    // Specify the layout to use when the list of choices appears
		                        	    logAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);    
		                        	    // Apply the adapter to the spinner
		                        	    graphLogTypeSpiner.setAdapter(logAdapter);
		                        	    //set the spinner to what the user set it to.
		                        	    graphLogTypeSpiner.setSelection(mSpinnerSelected);
		        		            }
		        				});               			               			
                			} else {
                				simpleDialog("You currently have no log data");            				
                			}
                		}  else{
                			//let the user know there was an error.
                			simpleDialog("Error Accessing Database");
                		}              		
                     }
                 } catch (Exception e) {
                	 //TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
                     simpleDialog("Network Connection Error");		        	 
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		
    }
    /**
     * Get Graph Data.
     * @param graphType
     */
    public void getGraphData(final String graphType){	
    	new Thread(new Runnable() {
    		@Override
            public void run() {            	
    			// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);            
                // will this be compared to other peoples data.
                String compare = "false";         	    	
                JSONFunctions userFunction = new JSONFunctions();
                final JSONObject json = userFunction.getGraphData(mUserID, mSessionToken, graphType, compare);               
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			if(!json.isNull("logs")){
	                			// successfully added all the points to the graph.
	                			runOnUiThread(new Runnable() {
	                	            public void run() {
			                			try {
			                				// make sure vector is empty before we add to it.
			                				vector.clear();
											for(int i = 0; i < json.getJSONArray("logs").length(); i++){
												//x plane
												vector.add((double) i);
												// y plane
												vector.add((double) json.getJSONArray("logs").getDouble(i));												
												mySeries = new GraphHolder(vector);					                			
												graphLayout.addSeries(mySeries, LineAndPointRenderer.class,
					                					new LineAndPointFormatter(Color.rgb(0, 200, 0), Color.rgb(200,
					                							0, 0)));
												graphLayout.redraw();					                								                			
					                			//Set of internal variables for keeping track of the boundaries
												graphLayout.calculateMinMaxVals();
					                			minXY=new PointF(graphLayout.getCalculatedMinX().floatValue(),graphLayout.getCalculatedMinY().floatValue());
					                			maxXY=new PointF(graphLayout.getCalculatedMaxX().floatValue(),graphLayout.getCalculatedMaxY().floatValue());
					                			//enable the graph incase it's disabled.
					                			runOnUiThread(new Runnable() {
				                					public void run() {
				                						graphLayout.setEnabled(true);
				                					}
				                				});
											}
										} catch (JSONException e) {
											//TODO better exception handling.
											simpleDialog("No graph data.");
										}           			
	                	            }
	                			});
                			} else {
                				runOnUiThread(new Runnable() {
                					public void run() {
                						graphLayout.setEnabled(false);
                					}
                				});
                				simpleDialog("You currently have no log data");
                			}
                		}else{
                			//let the user know there was an error.
							simpleDialog("Error Accessing Database.");
                		}  		
                     }
                 } catch (Exception e) {
                	 //TODO better exception handling.
                     simpleDialog("Network Connection Error.");
                 }
    		}                  	
    	}).start();		  	
    }
    /**
     * Create a simple dialog.
     * @param title
     */
    private void simpleDialog(final String title){
    	runOnUiThread(new Runnable() {
			public void run() {
				// new dialog
				final Dialog dialog = new Dialog(mCtx);
				dialog.setContentView(R.layout.popup);
				dialog.setTitle(title);		 	
				Button dialogButton = (Button) dialog.findViewById(R.id.dismiss);
				// if button is clicked, close the custom dialog
				dialogButton.setOnClickListener(new OnClickListener() {
					@Override
					public void onClick(View v) {
						dialog.dismiss();
					}
				});		 
				dialog.show();
			}
		}); 		
	}
    
	@SuppressWarnings("deprecation")
	@Override
	public boolean onTouch(View arg0, MotionEvent event) {
		try{
			switch (event.getAction() & MotionEvent.ACTION_MASK) {
			case MotionEvent.ACTION_DOWN: // Start gesture
				mFirstFinger = new PointF(event.getX(), event.getY());
				mMode = ONE_FINGER_DRAG;
				break;
			case MotionEvent.ACTION_UP: 
			case MotionEvent.ACTION_POINTER_UP:
				//When the gesture ends, a thread is created to give inertia to the scrolling and zoom 
				Timer t = new Timer();
					t.schedule(new TimerTask() {
						@Override
						public void run() {
							while(Math.abs(mLastScrolling)>1f || Math.abs(mLastZooming-1)<1.01){ 
							mLastScrolling*=.8;
							scroll(mLastScrolling);
							mLastZooming+=(1-mLastZooming)*.2;
							zoom(mLastZooming);
							graphLayout.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
							try {
								graphLayout.postRedraw();
							} catch (InterruptedException e) {
								e.printStackTrace();
							}
							// the thread lives until the scrolling and zooming are imperceptible
						}
						}
					}, 0);
			/*
			 * This function enables two finger zooming, without it, one finger scrolling is used.
			 * Disabled due to forced closure.
			 */
			case MotionEvent.ACTION_POINTER_2_DOWN: // second finger
				/*distBetweenFingers = spacing(event);
				// the distance check is done to avoid false alarms
				if (distBetweenFingers > 5f) {
					mode = TWO_FINGERS_DRAG;
				}
				*/
				break;
			case MotionEvent.ACTION_MOVE:
				if (mMode == ONE_FINGER_DRAG) {
					PointF oldFirstFinger=mFirstFinger;
					mFirstFinger=new PointF(event.getX(), event.getY());
					mLastScrolling=oldFirstFinger.x-mFirstFinger.x;
					scroll(mLastScrolling);
					mLastZooming=(mFirstFinger.y-oldFirstFinger.y)/graphLayout.getHeight();
					if (mLastZooming<0)
						mLastZooming=1/(1-mLastZooming);
					else
						mLastZooming+=1;
					zoom(mLastZooming);
					graphLayout.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
					graphLayout.redraw();
	
				} else if (mMode == TWO_FINGERS_DRAG) {
					float oldDist =mDistBetweenFingers; 
					mDistBetweenFingers=spacing(event);
					mLastZooming=oldDist/mDistBetweenFingers;
					zoom(mLastZooming);
					graphLayout.setDomainBoundaries(minXY.x, maxXY.x, BoundaryMode.AUTO);
					graphLayout.redraw();
				}
				break;
			}
			return true;

		} catch (Exception e){
			System.out.println("Graph Exception: " + e);
		}
		return true;
	}
	/**
	 *  Zoom graph function.
	 * @param scale
	 */
	private void zoom(float scale) {
		try{
			float domainSpan = maxXY.x	- minXY.x;
			float domainMidPoint = maxXY.x		- domainSpan / 2.0f;
			float offset = domainSpan * scale / 2.0f;
			minXY.x=domainMidPoint- offset;
			maxXY.x=domainMidPoint+offset;
		} catch ( Exception e){
			System.out.println("Zoom Exception: " + e);
		}
	}
	/**
	 * Scroll graph function.
	 * @param pan
	 */
	private void scroll(float pan) {
		try{
			float domainSpan = maxXY.x	- minXY.x;
			float step = domainSpan / graphLayout.getWidth();
			float offset = pan * step;
			minXY.x+= offset;
			maxXY.x+= offset;
		} catch (Exception e){
			System.out.println("Scroll Exception: " + e);
		}
	}
	/**
	 * Graph Spaccing.
	 * @param event
	 * @return
	 */
	private float spacing(MotionEvent event) {
		float x = event.getX(0) - event.getX(1);
		float y = event.getY(0) - event.getY(1);
		return FloatMath.sqrt(x * x + y * y);
	}
	/**
	 * Compare layout Setup.
	 * @param getLogErrorMsg
	 * @param logTable
	 * @param logTypeSpin
	 * @param valueTable
	 * @param comparisonTable
	 * @param dateTable
	 * @param allTable
	 */
	public void compareSetup( 
		final TextView getLogErrorMsg,
		final TableLayout logTable, 
		final Spinner logTypeSpin,
		final TableLayout valueTable,
		final TableLayout comparisonTable,
		final TableLayout dateTable, 
		final TableLayout allTable){
    	
    	this.mGetLogErrorMsg = getLogErrorMsg;
    	this.mLogTable = logTable;
        this.mLogTypeSpin = logTypeSpin;
        this.mValueTable = valueTable;
        this.mComparisonTable = comparisonTable;
        this.mDateTable = dateTable;
        this.mAllTable = allTable;
    	
        // used for refreshing.
    	mCurrentTab = 3;	        
    	//get the types of logs and setup the spinner.
    	mTypesBool = true;
    	mCompare = true;
    	//get the logs.
    	getLogs();    	
        dismissProgressDialog();	            	    	
    	// get data from local storage.
        StoreData store = new StoreData();
        // get user id from local storage
        mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
        // get session token from local storage
        mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION); 
    }	 
	/**
	 * Get comparative log data.
	 */
    public void getComparison(){  	  	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let user know it's busy.
            	createProgressDialog();
            	// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);
            	String type = mLogTypeIdArray.get(mSpinnerSelected);
            	// connect to server.           	
                JSONFunctions userFunction = new JSONFunctions();
                //TODO allow different types of ordering.
                JSONObject json = userFunction.getComparison(mUserID, mSessionToken, type, "date");            
                // remove all views from layout.
                runOnUiThread(new Runnable() {
    	            public void run() {
        			mValueTable.removeAllViews(); 
    	            mComparisonTable.removeAllViews(); 
    	            mDateTable.removeAllViews(); 
    			}});             
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// get comparison array.          	            
                			mJsonLogs = json.getJSONArray("comparison");
            	            //TODO order by date not finished.
                			if("date".equals("date")){
                				for(int i = mJsonLogs.length()-1; i >= 0; i--){             					          				               					
                					String value = "";
                					if(!mJsonLogs.getJSONObject(i).isNull("datalog_average")){
                						value = mJsonLogs.getJSONObject(i).getString("datalog_average");
                					}
                					String comparison = "";
                					if(!mJsonLogs.getJSONObject(i).isNull("benchmark_value")){
                    					comparison = mJsonLogs.getJSONObject(i).getString("benchmark_value");
                					}
                					String date = "";
                					if(!mJsonLogs.getJSONObject(i).isNull("benchmark_date")){
                						date = "";
                    					date = mJsonLogs.getJSONObject(i).getString("benchmark_date");
                					}               		
                					comparisonUiHandler(value, comparison, date); 			
                				}
                			} else {             			
	                			// go through all logs
	            				for(int i = mJsonLogs.length()-1; i >= 0; i--){	            					
	            					String value = mJsonLogs.getJSONObject(i).getString("datalog_value");
	            					String comparison = mJsonLogs.getJSONObject(i).getString("benchmark_value");
	            					String date = mJsonLogs.getJSONObject(i).getString("benchmark_date");
	            					// pass each log to Ui handler.
	            					comparisonUiHandler(value, comparison, date); 			
	            				}
                			}	            			
                		} else if(Integer.parseInt(res) == 3){
       		        	 	errorMessage("No Comparitive Data.");
                		} else{
                			//let the user know there was an error.
       		        	 	errorMessage("Error Accessing Database");
                		}              		
                     }
                 } catch (Exception e) {
                	 //TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
		        	 errorMessage("Network Connection Error");		        	 
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		
    }
    /**
     * UI handler for comparison logs.
     * @param valueStr
     * @param comparisonStr
     * @param dateStr
     */
    private void comparisonUiHandler(
    		final String valueStr,
    		final String comparisonStr,
    		final String dateStr){  	
    	runOnUiThread(new Runnable() {
            public void run() {
	           	 TextView value = new TextView(mCtx); 
	           	 value.setTextSize(18f);
	             value.setText(valueStr);	             
	             TextView comparison = new TextView(mCtx); 
	             comparison.setTextSize(18f);
	             comparison.setText(comparisonStr);	             
	             TextView date = new TextView(mCtx);  
	             date.setTextSize(18f);
	             date.setText(dateStr);	           	
	           	 // add views to the row
	             mValueTable.addView(value); 
	             mComparisonTable.addView(comparison); 
	             mDateTable.addView(date);    	 
            }
        });
    }
    /**
     * Symptoms layout setup.
     * @param getLogErrorMsg
     * @param logTable
     * @param logTypeSpin
     */
    public void symptomSetup(final TextView getLogErrorMsg,
    		final TableLayout logTable, final Spinner logTypeSpin){
    	
    	this.mGetLogErrorMsg = getLogErrorMsg;
    	this.mLogTable = logTable;
    	this.mLogTypeSpin = logTypeSpin;   	
    	// used for refreshing.
    	mCurrentTab = 4;
    	dismissProgressDialog();
    	// get data from local storage.
        StoreData store = new StoreData();
        // get user id from local storage
        mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
        // get session token from local storage
        mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);        
        //trigger, run rest of code on the same thread.
        mHistory = true;
        // get the history of logs.
        getSymptoms();
    }
    
    /**
     * Gets the logs from the server
     */
    public void getSymptoms(){      
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();           	
            	runOnUiThread(new Runnable() {
                    public void run() {
                    	// clear the table first
                        mLogTable.removeAllViews();            }
                });           	
            	// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);
            	// connect to server and get symptoms.
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.getSymptoms(mUserID, mSessionToken, "");                                            
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			if(!json.isNull("symptoms")){
                				mJsonLogs = json.getJSONArray("symptoms");              			
                				// get each symptom and send it to ui handler.
	                			for(int i = mJsonLogs.length() - 1; i >= 0; i--){
	                				String name = mJsonLogs.getJSONObject(i).getString("symptom_name");
	                				String value = mJsonLogs.getJSONObject(i).getString("symptom_level");
	                				String note = mJsonLogs.getJSONObject(i).getString("symptom_note");
	                				String id = mJsonLogs.getJSONObject(i).getString("symptom_id");                				    
	                				if(value.equals("1")){
	                					value = "Mild";
	                				} else if(value.equals("2")){
	                					value = "Average";
	                				} else if(value.equals("3")){
	                					value = "Severe";
	                				}               				
	                				logsUiHandler(name, value, "", note, id, "symptoms");
	                			} 
                			} else {
           		        	 	errorMessage("You currently have no log data");
                			}            			
                		}else{
                			//let the user know there was an error.
       		        	 	errorMessage("Error Accessing Database");
                		}
                		
                     }
                 } catch (Exception e) {
                	 //TODO better exceptino handling.
                     e.printStackTrace();
                     // let the user know there was an error.
		        	 errorMessage("Network Connection Error");		        	 
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		
    }
    /**
     * Setup for the log history layout.
     * @param getLogErrorMsg
     * @param logTable
     * @param logTypeSpin
     */
    public void logHistorySetup(final TextView getLogErrorMsg,
    		final TableLayout logTable, final Spinner logTypeSpin){
    	
    	this.mGetLogErrorMsg = getLogErrorMsg;
    	this.mLogTable = logTable;
    	this.mLogTypeSpin = logTypeSpin;    	
    	// used for refreshing.
    	mCurrentTab = 2;
    	// reset selection type.
    	mSpinnerSelected = 0;    	
    	dismissProgressDialog();    	    	
    	// get data from local storage.
        StoreData store = new StoreData();
        // get user id from local storage
        mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
        // get session token from local storage
        mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);       
        //trigger, run rest of code on the same thread.
        mHistory = true;
        // get the history of logs.
        getLogs();
    }
    /**
     *  Setup for the Food log layout.
     * @param getLogErrorMsg
     * @param logTable
     * @param logTypeSpin
     */
    public void logFoodSetup(final TextView getLogErrorMsg,
    		final TableLayout logTable, final Spinner logTypeSpin){
    	
    	this.mGetLogErrorMsg = getLogErrorMsg;
    	this.mLogTable = logTable;
    	this.mLogTypeSpin = logTypeSpin;  	
    	// used for refreshing.
    	mCurrentTab = 0;   	
    	dismissProgressDialog();   	    	
    	// get data from local storage.
        StoreData store = new StoreData();
        // get user id from local storage
        mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
        // get session token from local storage
        mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);        
        //trigger, run rest of code on the same thread.
        mHistory = true;
        // get the history of logs.
        getFood();
    }
    /**
     * Get the food logs from the server.
     */
    public void getFood(){     
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();            	
            	runOnUiThread(new Runnable() {
                    public void run() {
                    	// clear the table first
                        mLogTable.removeAllViews();            }
                });            	
            	// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);
            	// connect to server and get food log list.
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.getFood(mUserID, mSessionToken, "");                                        
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			if(!json.isNull("foodList")){
	                			mJsonLogs = json.getJSONArray("foodList");              			         			
	                			for(int i = mJsonLogs.length() - 1; i >= 0; i--){
	                				String name = mJsonLogs.getJSONObject(i).getString("food_name");
	                				String value = mJsonLogs.getJSONObject(i).getString("food_calories");
	                				String note = mJsonLogs.getJSONObject(i).getString("food_note");
	                				String id = mJsonLogs.getJSONObject(i).getString("food_id");
	                				// pass each food log to UI handler.
	                				logsUiHandler(name, value, "", note, id, "food");
	                			}   
                			} else {
           		        	 	errorMessage("You currently have no log data");
                			}
	            			
                		}else{
                			//let the user know there was an error.
       		        	 	errorMessage("Error Accessing Database");
                		}
                		
                     }
                 } catch (Exception e) {
                	 // TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
		        	 errorMessage("Network Connection Error");		        	 
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		
    }
    /**
     * Dialog to add a food log.
     */
    public void addFoodSetup(){
    	createProgressDialog();
    	// used for refreshing.
    	mCurrentTab = 0; 
    	// custom dialog
		final Dialog dialog = new Dialog(mCtx);
		dialog.setContentView(R.layout.add_food);
		dialog.setTitle("Add Food");		
        mAdd = (Button) dialog.findViewById(R.id.add);
        //getLogErrorMsg = (TextView) dialog.findViewById(R.id.error_text);
    	mNotesText = (EditText) dialog.findViewById(R.id.notesInput);
    	mFoodText = (EditText) dialog.findViewById(R.id.food);
    	mCaloriesText = (EditText) dialog.findViewById(R.id.calories);		
		Button dialogButton = (Button) dialog.findViewById(R.id.dismiss);
		// if button is clicked, close the custom dialog
		dialogButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
		dialog.show();        
		// empty fields.
        mNotesText.setText("");
        mCaloriesText.setText("");
        mFoodText.setText("");
 
		//back button
		mAdd.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				//close intent.
		   		addFood(mFoodText, mNotesText, mCaloriesText, dialog);
		   	}
		});
          
        //hide progress bar - thread will handle showing it.
         dismissProgressDialog();
    }
    /**
     * Add food log to user.
     * @param foodText
     * @param notesText
     * @param caloriesText
     * @param dialog
     */
    public void addFood (
    		final EditText foodText, 
    		final EditText notesText, 
    		final EditText caloriesText, 
    		final Dialog dialog){
    	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();
            	// get values the user has entered.       	            	
            	String food = foodText.getText().toString();            	
            	String calories = caloriesText.getText().toString();            	
            	String notes = notesText.getText().toString();            	
            	// connect to server and add log to user.   	
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.addFood(mUserID, mSessionToken, food, calories, notes);
                 // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// successfully added log, refresh layout.	
                			dialog.dismiss();
                			refresh();
                		}else{
							simpleDialog("Error Accessing Database.");
                		}  		
                     }
                 } catch (Exception e) {
                	 //TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
                     simpleDialog("Network Connection Error");
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		  	
    }
    /**
     * Add a symptom to the user.
     */
    public void addSymptomSetup(){
    	// new dialog
		final Dialog dialog = new Dialog(mCtx);
		dialog.setContentView(R.layout.symptoms);
		dialog.setTitle("Add Symptom");
        mAdd = (Button) dialog.findViewById(R.id.add);
        mSeveritySpin = (Spinner) dialog.findViewById(R.id.severity);
        mLogTypeSpin = (Spinner) dialog.findViewById(R.id.logsSpinner);
        //getLogErrorMsg = (TextView) dialog.findViewById(R.id.error_text);
    	mNotesText = (EditText) dialog.findViewById(R.id.notesInput);
    	mSymptomsText = (EditText) dialog.findViewById(R.id.symptoms);		
		Button dialogButton = (Button) dialog.findViewById(R.id.dismiss);
		// if button is clicked, close the custom dialog
		dialogButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
		dialog.show();
		// let the user know it's busy.
		createProgressDialog();
		// empty fields.
        mNotesText.setText("");
    	mSymptomsText.setText("");             
    	// Set listener to Spinner                
        mSeveritySpin.setOnItemSelectedListener(new OnItemSelectedListener() {
    	    @Override
    	    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
                mSeverityStr = Integer.toString(position + 1);
    	    }
    	    @Override
    	    public void onNothingSelected(AdapterView<?> parentView) {
    	        // your code here
    	    }	
    	});       
	    // Create an ArrayAdapter using the string array and a default spinner layout	    
        mSeverityStringArray.clear();
        mSeverityStringArray.add("Mild");
        mSeverityStringArray.add("Average");
        mSeverityStringArray.add("Severe");       
        ArrayAdapter<String> severityAdapter = new ArrayAdapter<String>(mCtx,
	    		android.R.layout.simple_spinner_item, mSeverityStringArray);  	    
	    // Specify the layout to use when the list of choices appears
	    severityAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);    
	    // Apply the adapter to the spinner
        mSeveritySpin.setAdapter(severityAdapter);
          
        //back button
        mAdd.setOnClickListener(new OnClickListener() {
        	public void onClick(View v) {
        		//close intent.
           		addSymptom(mNotesText, mSymptomsText, dialog);
           	}
        });        
        //hide progress bar - thread will handle showing it.
        dismissProgressDialog();
    }
    /**
     * Add symptom to user.
     * @param notesText
     * @param symptomsText
     * @param dialog
     */
    public void addSymptom (final EditText notesText, final EditText symptomsText, final Dialog dialog){  	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();
            	// get values the user has entered.           	            	
            	String notes = notesText.getText().toString();            	
            	String symptoms = symptomsText.getText().toString();
            	// connect to server and add symptom.   	
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.addSymptom(mUserID, mSessionToken, notes, symptoms, mSeverityStr);
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// successfully added log, refresh layout.	
                			dialog.dismiss();
                			refresh();
                		}else{
							simpleDialog("Error Accessing Database.");
                		}  		
                     }
                 } catch (Exception e) {
                	 //TODO better eception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
					simpleDialog("Network Connection Error");
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		  	
    }
    /**
     * Setup dialog to add a log.
     */
    public void addLogSetup(){
    	// used for refreshing.
    	mCurrentTab = 2;    	
    	// new dialog
		final Dialog dialog = new Dialog(mCtx);
		dialog.setContentView(R.layout.logdata);
		dialog.setTitle("Add Log");
        mAdd = (Button) dialog.findViewById(R.id.add);
        mLogTypeSpin = (Spinner) dialog.findViewById(R.id.logsSpinner);
        // getLogErrorMsg = (TextView) dialog.findViewById(R.id.error_text);
    	mValueText = (EditText) dialog.findViewById(R.id.valueInput);
    	mNotesText = (EditText) dialog.findViewById(R.id.notesInput);		
		Button dialogButton = (Button) dialog.findViewById(R.id.dismiss);
		// if button is clicked, close the custom dialog
		dialogButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});        
		// empty fields.
    	mValueText.setText("");
        mNotesText.setText("");        
        //when we get logs, we're getting the spinner fields
        mTypesBool = true;
        mHistory = false;
        mDialogBool = true;
        //get log types.
        getLogs();     
		 //back button
        mAdd.setOnClickListener(new OnClickListener() {
			public void onClick(View v) {
				addLog(mValueText, mNotesText, dialog);
			}
        });		  
		dialog.show();       
    }
    /**
     * Add a log to the user.
     * @param valueText
     * @param notesText
     * @param dialog
     */
    public void addLog(final EditText valueText, final EditText notesText, final Dialog dialog){
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();
            	// get values the user has entered.          	
            	String value = valueText.getText().toString();          	
            	String notes = notesText.getText().toString();          	            	
            	String type = mLogTypeIdArray.get(mSpinnerSelected);   	
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.addLog(mUserID, mSessionToken, type, value, notes);
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// successfully added log, refresh layout.
                			dialog.dismiss();
                			refresh();
                		}else{
							simpleDialog("Error Accessing Database.");
                		}  		
                     }
                 } catch (Exception e) {
                	 // TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
					simpleDialog("Network Connection Error");
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();		  	
    }
    
    /**
     * Get the logs the user has added.
     */
    public void getLogs(){   	  	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    	    	// let the use know it's busy.
            	createProgressDialog();       		
        		//make sure these are empty - avoids duplicate values.
				if(!mDialogBool == true){
	            	//hide error message from user.
	        		emptyErrorMessage();
	        		runOnUiThread(new Runnable() {
			            public void run() {
			            	if(mLogTable != null){
			            		mLogTable.removeAllViews();
			            	}
			            }
					});
	        		mDialogBool = false;
				}
            	// get data from local storage.
                StoreData store = new StoreData();
                // get user id from local storage
                mUserID = (String) store.openType(mCtx, String.class, KEY_UID);
                // get session token from local storage
                mSessionToken = (String) store.openType(mCtx, String.class, KEY_SESSION);
            	// connect to server and get logs
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.getLogs(mUserID, mSessionToken);                         
                 // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {             		
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// make sure data log type isn't null
                			if(!json.isNull("dataTypeList")){
		            			mJsonTypes = json.getJSONArray("dataTypeList");
		            			//make sure these are empty - avoids dublicate values.
		            			mLogTypeStringArray.clear();
		            			mLogTypeIdArray.clear();		            			
		            			// if history, add the All option.
		            			if(mHistory == true){
		           				 	mLogTypeStringArray.add("All");		
		            			}		            			
		            			// add the type names to a string array.
		            			for(int n = 0; n < mJsonTypes.length(); n++){
		            				String name = mJsonTypes.getJSONObject(n).getString("datalog_type_name");
		            				//convert the first character to uppercase.
		            				name = name.substring(0, 1).toUpperCase() + name.substring(1);                				
		            				mLogTypeStringArray.add(name);
		            				// get the id numbers in the same order as the names ->used for adding log.
		            				mLogTypeIdArray.add(mJsonTypes.getJSONObject(n).getString("datalog_type_id"));
		            			}	            			
		            			// checks if user clicked, stop device from automatically setting the item and looping the function.
		        				mHuman = false;																
								mLogTypeSpin.setOnItemSelectedListener(new OnItemSelectedListener() {
		    		        	    @Override
		    		        	    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
		    		        	    	mSpinnerSelected = position;
		    		        	    	mHistory = true;
		    		        	    	if(mHuman){
		    		        	    		getLogs();
		    		        	    	}
		    		        	    	mHuman = false;
		    		        	    }
		    		        	    @Override
		    		        	    public void onNothingSelected(AdapterView<?> parentView) {
		    		        	        // do nothing
		    		        	    }                   		        
								});		        		        
		        				// Create an ArrayAdapter using the string array and a default spinner layout	    
		        				runOnUiThread(new Runnable() {
		        		            public void run() {		
		                				mLogAdapter = new ArrayAdapter<String>(mCtx,
		                        	    		android.R.layout.simple_spinner_item, mLogTypeStringArray);  	    
		                        	    // Specify the layout to use when the list of choices appears
		                        	    mLogAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);    
		                        	    // Apply the adapter to the spinner
		                        	    mLogTypeSpin.setAdapter(mLogAdapter);
		                        	    //set the spinner to what the user set it to.
		                				mLogTypeSpin.setSelection(mSpinnerSelected);
		        		            }
		        				});
                			}
                			// check if log list isn't null.
                			if(!json.isNull("logList")){
                				mJsonLogs = json.getJSONArray("logList");          		                			
	                			if(mHistory == true){
	                				String type = "";  					                				
	                		    	// go through all logs
	                				for(int i = mJsonLogs.length()-1; i >= 0; i--){
	                					//go through each type of log
	                					for(int n = 0; n < mJsonTypes.length(); n++){
	                						// if log type in logs array matches types array, then we know what type	
	                						if(mJsonLogs.getJSONObject(i).getString("datalog_type_id").equals(mJsonTypes.getJSONObject(n).getString("datalog_type_id"))){
	                							type = mJsonTypes.getJSONObject(n).getString("datalog_type_name");
	                						}
	                					}
	                					// get each log details.
	                					String value = mJsonLogs.getJSONObject(i).getString("datalog_value");
	                					String unit = mJsonLogs.getJSONObject(i).getString("datalog_unit");
	                					String note = mJsonLogs.getJSONObject(i).getString("datalog_note");
	                					String id = mJsonLogs.getJSONObject(i).getString("datalog_id");	                			
	                					// if type is the type that's selected, then proceed
	                					if(mSpinnerSelected == 0 || type.equalsIgnoreCase(mLogTypeSpin.getItemAtPosition(mSpinnerSelected).toString())){
	                    					logsUiHandler(type, value, unit, note, id, "logs"); 	
	                					}			                		
	                				} 
	                				mHistory = false;	                				
	                			} 
	                			if(mTypesBool == true){
	                				runOnUiThread(new Runnable() {
	                		            public void run() {
	                		                // if comparison layout is true, then run function on click.        		            	
	                		            	if(mCompare == true){
	                		            		mLogTypeSpin.setOnItemSelectedListener(new OnItemSelectedListener() {
	     	                		        	    @Override
	     	                		        	    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
	     	                		        	    	mSpinnerSelected = position;
	     	                			    	        getComparison();
	     	                		        	    }    	
	     	                		        	    @Override
	     	                		        	    public void onNothingSelected(AdapterView<?> parentView) {
	     	                		        	        // do nothing.
	     	                		        	    }	
	     	                		        	});
	                		            		mCompare = false;
	                		            	} else {
			                		           mLogTypeSpin.setOnItemSelectedListener(new OnItemSelectedListener() {
			                		        	    @Override
			                		        	    public void onItemSelected(AdapterView<?> parentView, View selectedItemView, int position, long id) {
			                		        	    	mSpinnerSelected = position;	
			                		        	    }
			                		        	    @Override
			                		        	    public void onNothingSelected(AdapterView<?> parentView) {
			                		        	        // your code here
			                		        	    }	
			                		        	});
	                		            	}	                		           
			                        	    // Create an ArrayAdapter using the string array and a default spinner layout	    
			                        	    mLogAdapter = new ArrayAdapter<String>(mCtx,
			                        	    		android.R.layout.simple_spinner_item, mLogTypeStringArray);  	    
			                        	    // Specify the layout to use when the list of choices appears
			                        	    mLogAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);    
			                        	    // Apply the adapter to the spinner
			                        	    mLogTypeSpin.setAdapter(mLogAdapter);
			                        	    mTypesBool = false;
	                		            }
	                				});
	                			}
	                			errorMessage("");

                			} else {
                				if (!mDialogBool){
           		        	 		errorMessage("You currently have no log data");
                				}
                			}
                		}  else{
                			//let the user know there was an error.
       		        	 	errorMessage("Error Accessing Database");
                		}              		
                     }
                 } catch (Exception e) {
                     e.printStackTrace();
                     // let the user know there was an error.
		        	 errorMessage("Network Connection Error");		        	 
                 }
 				 mDialogBool = false;
                 dismissProgressDialog();
    		}                  	
    	}).start();		
    }   
    /**
     * The logs UI handler.
     * @param name
     * @param value
     * @param unit
     * @param note
     * @param logId
     * @param type
     */
    private void logsUiHandler(
    		final String name,
    		final String value,
    		final String unit,
    		final String note,
    		final String logId,
    		final String type){
    	
    	runOnUiThread(new Runnable() {
            public void run() {
            	// Create Column for patients name.	 
	           	// declare a new row
	           	TableRow row = new TableRow(mCtx);
	           	// create text view.
	           	TextView text = new TextView(mCtx);
	           	text.setTextSize(18f);           	 
	           	String tempUnit = unit;
	           	if("null".equals(tempUnit)){
	           		tempUnit = "";
	           	}           	 
	            text.setText(asUpperCaseFirstChar(name) + ": " + value + " " + tempUnit);           	
	           	// add views to the row
	           	row.addView(text); // you would actually want to set properties on this before adding it
	           	row.setPadding(10, 10, 0, 10);	        
	           	row.setOnClickListener(new View.OnClickListener() {
	           		public void onClick(View v) {
	                	logsDialog(R.layout.popup, name,  value, note, logId, type);          	
	                }
	            }); 	           	 
	           	// Used for creating a horizontal line to separate .	           	          	           	 
	           	View ruler = new View(mCtx); ruler.setBackgroundColor(mRulerColour);
	           	mLogTable.addView(ruler, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 2));	           	
	           	 // add the row to the table layout
	           	mLogTable.addView(row);      	 
            }
        });
    }
    /**
     * Confirm delete dialog before deleting log.
     * @param deleteDialog
     * @param title
     * @param logId
     * @param type
     */
    private void confirmDelete(final Dialog deleteDialog, final String title, final String logId, final String type){
		// new dialog
		final Dialog confirmDialog = new Dialog(mCtx);
		confirmDialog.setContentView(R.layout.confirm_popup_dialog);
		confirmDialog.setTitle("Confirm Delete");				
		Button deleteButton = (Button) confirmDialog.findViewById(R.id.delete);
		// if button is clicked, close the custom dialog
		deleteButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				deleteLog(deleteDialog, logId, type);
				confirmDialog.dismiss();
			}
		});                     	
		Button cancelButton = (Button) confirmDialog.findViewById(R.id.cancel);
		// if button is clicked, close the custom dialog
		cancelButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				deleteDialog.dismiss();
				confirmDialog.dismiss();
			}
		});
		confirmDialog.show();
		deleteDialog.hide();
		
	}  
    /**
     * returns the string, the first char uppercase
     *
     * @param target
     * @return
     */
    public final static String asUpperCaseFirstChar(final String target) {

        if ((target == null) || (target.length() == 0)) {
            return target; 
        }
        return Character.toUpperCase(target.charAt(0))
                + (target.length() > 1 ? target.substring(1) : "");
    }
    
    /*dialog of patients, only shows details of the hospital.*
     * 
     * @param itemsPopup
     * @param title
     * @param value
     * @param note
     * @param logId
     * @param type
     */
    private void logsDialog(int itemsPopup, final String title, final String value,
    		final String note, final String logId, final String type){

		// custom dialog
		final Dialog dialog = new Dialog(mCtx);
		dialog.setContentView(itemsPopup);
		dialog.setTitle(title);
		// create rows
		TableRow valueRow = new TableRow(mCtx);
		TableRow noteRow = new TableRow(mCtx);
      	// create text view.
      	TextView valueTx = new TextView(mCtx);
      	TextView noteTx = new TextView(mCtx);
      	// set text
      	valueTx.setText("Value: " + value);
      	noteTx.setText("Note: " + note);
      	// add views to the row
      	valueRow.addView(valueTx);
      	noteRow.addView(noteTx);
      	// set padding.
      	valueRow.setPadding(10, 20, 0, 0);
      	noteRow.setPadding(10, 20, 0, 0);
      	// create table
      	TableLayout dialogTable = (TableLayout) dialog.findViewById(R.id.dialogTable);           
      	 // add the row to the table layout
      	dialogTable.addView(valueRow);
      	dialogTable.addView(noteRow);
     	// create delete button.
      	Button deleteButton = new Button(mCtx);
      	deleteButton.setText("Delete");      	
		// if button is clicked, close the custom dialog
      	deleteButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				confirmDelete(dialog, title, logId, type);
			}
		});
      	// add table to view.
      	dialogTable.addView(deleteButton);
      	// dissmiss button.
		Button dialogButton = (Button) dialog.findViewById(R.id.dismiss);
		// if button is clicked, close the custom dialog
		dialogButton.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				dialog.dismiss();
			}
		});
		dialog.show();
	}
    /**
     * Delete log associated with user.
     * @param dialog
     * @param logId
     * @param type
     */
    private void deleteLog(final Dialog dialog, final String logId, final String type){  	
    	new Thread(new Runnable() {
    		@Override
            public void run() {
    			// let the user know it's busy.
            	createProgressDialog();
            	// connect to server and delete log.
                JSONFunctions userFunction = new JSONFunctions();
                JSONObject json = userFunction.deleteLog(mUserID, mSessionToken, logId, type);
                // check for login response
                try {
                	if (json.getString(KEY_SUCCESS) != null) {
                		//hide error message from user.
                		emptyErrorMessage();
                		String res = json.getString(KEY_SUCCESS);
                		if(Integer.parseInt(res) == 1){
                			// successfully added log, refresh layout.
                			dialog.dismiss();
                			refresh();
                		}else{
							simpleDialog("Error Accessing Database.");
							// show the dialog again so the user doesn't lose place.
							dialog.show();
                		}  		
                     }
                 } catch (Exception e) {
                	 //TODO better exception handling.
                     e.printStackTrace();
                     // let the user know there was an error.
					simpleDialog("Network Connection Error");
					// show the dialog again so the user doesn't lose place.
					dialog.show();
                 }
                 dismissProgressDialog();
    		}                  	
    	}).start();	
    }
    /**
     * Empty the error message.
     */
    private void emptyErrorMessage(){
    	runOnUiThread(new Runnable() {
			public void run() {
				mGetLogErrorMsg.setText("");
				mGetLogErrorMsg.setVisibility(View.INVISIBLE);
            }
		});
    }
    /**
     * Create error message.
     * @param error
     */
    private void errorMessage(final String error){
    	runOnUiThread(new Runnable() {
			public void run() {
				mGetLogErrorMsg.setText(error);
				mGetLogErrorMsg.setVisibility(View.VISIBLE);
            }
		});
    }
    /**
     * Dismiss the progress spinner.   
     */
    private void dismissProgressDialog(){
    	runOnUiThread(new Runnable() {
            public void run() {
            	// hide progress spinner now that thread is finished.
            	if(mLoadingDialog != null){
            		mLoadingDialog.dismiss();
            	}
            }
        });
    }
    /**
     * Create progress spinner
     */
    private void createProgressDialog(){
    	runOnUiThread(new Runnable() {
            public void run() {
            	mLoadingDialog = new ProgressDialog(mCtx);
    	        mLoadingDialog.setTitle("");
    	        mLoadingDialog.setMessage("Loading. Please wait...");
            	mLoadingDialog.show();
            	// show progress spinner to let the user know it's working.
            }
        });
    }
    
    /**
     * Reloads current view.
     */
    private void refresh(){	
    	switch (mCurrentTab){
        case 0:
        	logFoodSetup(mGetLogErrorMsg, mLogTable, mLogTypeSpin);
        	break;
        case 1:
        	logGraphSetup(graphLayout, graphLogTypeSpiner);
        	break;
        case 2:
        	logHistorySetup(mGetLogErrorMsg, mLogTable, mLogTypeSpin);
        	break;
        case 3:
        	compareSetup(mGetLogErrorMsg, mLogTable, mLogTypeSpin, 
            		mValueTable, mComparisonTable, mDateTable, mAllTable);
        	break;      	
        case 4: 
        	symptomSetup(mGetLogErrorMsg, mLogTable, mLogTypeSpin);
        	break;

        default:
        	logHistorySetup(mGetLogErrorMsg, mLogTable, mLogTypeSpin);
    		break;
        }
   }  
}
